#!/usr/bin/env python
# coding:utf-8

import sys, os, time, json


def writeSpeed(title, used, total, speed=0):
    import json
    if not title:
        data = {'title': None, 'progress': 0, 'total': 0, 'used': 0, 'speed': 0}
    else:
        progress = int((100.0 * used / total))
        data = {'title': title, 'progress': progress, 'total': total, 'used': used, 'speed': speed}
    writeFile('/tmp/panelSpeed.pl', json.dumps(data))
    return True


def serviceReload():
    # 重载Web服务配置
    if os.path.exists('/www/server/nginx/sbin/nginx'):
        result = ExecShell('/etc/init.d/nginx reload')
        if result[1].find('nginx.pid') != -1:
            ExecShell('pkill -9 nginx && sleep 1')
            ExecShell('/etc/init.d/nginx start')
    else:
        result = ExecShell('/etc/init.d/httpd reload')
    return result


def get_webserver():
    webserver = 'nginx'
    if not os.path.exists('/www/server/nginx/sbin/nginx'): webserver = 'apache'
    return webserver


def checkWebConfig():
    if get_webserver() == 'nginx':
        result = ExecShell("ulimit -n 10240 && /www/server/nginx/sbin/nginx -t -c /www/server/nginx/conf/nginx.conf")
        searchStr = 'successful'
    else:
        result = ExecShell("ulimit -n 10240 && /www/server/apache/bin/apachectl -t")
        searchStr = 'Syntax OK'

    if result[1].find(searchStr) == -1:
        # WriteLog("TYPE_SOFT", 'CONF_CHECK_ERR', (result[1],))
        return result[1]
    return True


def ExecShell(cmdstring, cwd=None, timeout=None, shell=True):
    import shlex
    import datetime
    import subprocess
    import time

    if shell:
        cmdstring_list = cmdstring
    else:
        cmdstring_list = shlex.split(cmdstring)
    if timeout:
        end_time = datetime.datetime.now() + datetime.timedelta(seconds=timeout)

    sub = subprocess.Popen(cmdstring_list, cwd=cwd, stdin=subprocess.PIPE, shell=shell, bufsize=4096,
                           stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    while sub.poll() is None:
        time.sleep(0.1)
        if timeout:
            if end_time <= datetime.datetime.now():
                raise Exception("Timeout：%s" % cmdstring)

    return sub.communicate()



def writeFile(filename, str):
    # 写文件内容
    # print("writefile body", str)
    try:
        fp = open(filename, 'wb+')
        fp.write(str)
        fp.close()
        return True
    except:
        return False


def readFile(filename):
    # 读文件内容
    try:
        fp = open(filename, 'rb')
        fBody = fp.read()
        fp.close()
        return fBody
    except:
        return False


def returnMsg(status, msg, args=()):
    import json
    # 取通用字曲返回
    logMessage = json.loads(readFile('static/language/Simplified_Chinese/public.json'))
    keys = logMessage.keys()
    if msg in keys:
        msg = logMessage[msg]
        for i in range(len(args)):
            rep = '{' + str(i + 1) + '}'
            msg = msg.replace(rep, args[i])
    return {'status': status, 'msg': msg}


class files:
    # 检查敏感目录
    def __init__(self):
        self.BASE_DIR = os.path.dirname(os.path.abspath(__file__))

    def CheckDir(self, path):
        path = path.replace('//', '/')
        if path[-1:] == '/':
            path = path[:-1]
        nDirs = ('',
                 '/',
                 '/*',
                 '/www',
                 '/root',
                 '/boot',
                 '/bin',
                 '/etc',
                 '/home',
                 '/dev',
                 '/sbin',
                 '/var',
                 '/usr',
                 '/tmp',
                 '/sys',
                 '/proc',
                 '/media',
                 '/mnt',
                 '/opt',
                 '/lib',
                 '/srv',
                 '/selinux',
                 '/www/server',
                 '/www/server/data',
                 )
        for dir in nDirs:
            if (dir == path):
                return False
        return True

    def getSpeed(self):
        import json
        data = readFile('/tmp/panelSpeed.pl')
        if not data:
            data = json.dumps({'title': None, 'progress': 0, 'total': 0, 'used': 0, 'speed': 0})
            writeFile('/tmp/panelSpeed.pl', data)
        # print("getSpeed:", data)
        return data

    def GetDiskInfo(self):
        # 取磁盘分区信息
        temp = ExecShell("df -h -P|grep '/'|grep -v tmpfs")[0]
        tempInodes = ExecShell("df -i -P|grep '/'|grep -v tmpfs")[0]
        temp1 = bytes.decode(temp).split('\n')
        tempInodes1 = bytes.decode(tempInodes).split('\n')
        diskInfo = []
        n = 0
        cuts = ['/mnt/cdrom', '/boot', '/boot/efi', '/dev', '/dev/shm', '/run/lock', '/run', '/run/shm', '/run/user']
        for tmp in temp1:
            n += 1
            inodes = tempInodes1[n - 1].split()
            disk = tmp.split()
            if len(disk) < 5: continue;
            if disk[1].find('M') != -1: continue;
            if disk[1].find('K') != -1: continue;
            if len(disk[5].split('/')) > 4: continue;
            if disk[5] in cuts: continue;
            arr = {}
            arr['path'] = disk[5]
            tmp1 = [disk[1], disk[2], disk[3], disk[4]]
            arr['size'] = tmp1
            arr['inodes'] = [inodes[1], inodes[2], inodes[3], inodes[4]]
            if disk[5] == '/':
                bootLog = '/tmp/panelBoot.pl'
                if disk[2].find('M') != -1:
                    if os.path.exists(bootLog): os.system('rm -f ' + bootLog)
            diskInfo.append(arr)
        return diskInfo

    # 检测文件名
    def CheckFileName(self, filename):
        nots = ['\\', '&', '*', '#', '@', '|']
        if filename.find('/') != -1: filename = filename.split('/')[-1]
        for n in nots:
            if n in filename: return False
        return True

    # 上传文件
    # def UploadFile(self,get):
    #     get.path = get.path.encode('utf-8')
    #     fname = get['zunfile'].filename
    #     if fname.find(':\\') != -1:
    #         tmp = fname.split('\\')
    #         fname = tmp[len(tmp)-1]
    #     try:
    #         if not os.path.exists(get.path): os.makedirs(get.path)
    #         filename = (get['path'] + fname).encode('utf-8')
    #         fp = open(filename,'wb')
    #         fp.write(get['zunfile'].file.read())
    #         fp.close()
    #         if(get.codeing != 'byte'):
    #             srcBody = readFile(filename)
    #             import chardet
    #             char=chardet.detect(srcBody)
    #             srcBody = srcBody.decode(char['encoding']).encode('utf-8')
    #             public.writeFile(filename,srcBody.encode(get.codeing))
    #         os.system('chown www.www ' + filename)
    #         public.WriteLog('TYPE_FILE','FILE_UPLOAD_SUCCESS',(fname,get['path']))
    #         return public.returnMsg(True,'FILE_UPLOAD_SUCCESS')
    #     except:
    #         import time
    #         opt = time.strftime('%Y-%m-%d_%H%M%S',time.localtime())
    #         tmp = fname.split('.')
    #         if len(tmp) < 2:
    #             ext = ""
    #         else:
    #             ext = "." + tmp[-1]
    #         filename = get['path'] + "New_uploaded_files_" + opt + ext
    #         fp = open(filename.encode('utf-8'),'wb')
    #         fp.write(get['zunfile'].file.read())
    #         fp.close()
    #         os.system('chown www.www ' + filename)
    #         public.WriteLog('TYPE_FILE','FILE_UPLOAD_SUCCESS',(fname,get['path']))
    #         return public.returnMsg(True,'FILE_UPLOAD_SUCCESS')

    # 取文件/目录列表
    def GetDir(self, get, posts):
        path = bytes.decode(posts.get('path').encode('utf-8'))
        while path.startswith('/'):
            path = path[1:]
        path = os.path.join("/", path)
        if not os.path.exists(path): path = '/'
        import pwd
        dirnames = []
        filenames = []
        # print(get)
        search = None
        if 'search' in get: search = get.get('search').strip().lower()

        # 包含分页类
        from . import page
        # 实例化分页类
        page = page.Page()
        info = {}
        info['count'] = self.GetFilesCount(path, search)
        info['row'] = 100
        info['p'] = 1
        if 'p' in get:
            try:
                info['p'] = int(get.get('p'))
            except:
                info['p'] = 0
        info['uri'] = {}
        info['return_js'] = ''
        if 'tojs' in get:
            info['return_js'] = get.get('tojs')
        if 'showRow' in get:
            info['row'] = int(get.get('showRow'))

        # 获取分页数据
        data = {}
        # print(info)
        data['PAGE'] = page.GetPage(info, '1,2,3,4,5,6,7,8')

        i = 0
        n = 0
        for filename in os.listdir(path):
            if search:
                if filename.lower().find(search) == -1: continue
            i += 1
            if n >= page.ROW: break
            if i < page.SHIFT: continue

            try:
                filePath = os.path.join(path, filename).encode('utf8')
                link = ''
                if os.path.islink(filePath):
                    filePath = os.readlink(filePath)
                    link = ' -> ' + bytes.decode(filePath)
                    if not os.path.exists(filePath): filePath = os.path.join(path, bytes.decode(filePath))

                    if not os.path.exists(filePath): continue

                stat = os.stat(filePath)
                accept = str(oct(stat.st_mode)[-3:])
                mtime = str(int(stat.st_mtime))
                user = ''
                try:
                    user = pwd.getpwuid(stat.st_uid).pw_name
                except:
                    user = str(stat.st_uid)
                size = str(stat.st_size)
                if os.path.isdir(filePath):
                    dirnames.append(filename + ';' + size + ';' + mtime + ';' + accept + ';' + user + ';' + link)
                else:
                    filenames.append(filename + ';' + size + ';' + mtime + ';' + accept + ';' + user + ';' + link)
                n += 1
            except:
                continue

        data['DIR'] = sorted(dirnames)
        data['FILES'] = sorted(filenames)
        data['PATH'] = path
        if 'disk' in get:
            data['DISK'] = self.GetDiskInfo()
        return data

    # 计算文件数量
    def GetFilesCount(self, path, search):
        i = 0
        for name in os.listdir(path):
            if search:
                if name.lower().find(search) == -1: continue
            i += 1
        return i

    # 创建文件
    def CreateFile(self, get):
        path = bytes.decode(get.get('path').encode('utf-8'))
        while path.startswith('/'):
            path = path[1:]
        path = os.path.join("/", path)
        try:
            if not self.CheckFileName(path): return returnMsg(False, '文件名中不能包含特殊字符!')
            if os.path.exists(path):
                return returnMsg(False, 'FILE_EXISTS')
            pathdirname = os.path.dirname(path)
            if not os.path.exists(pathdirname):
                os.makedirs(pathdirname)
            open(path, 'wb+').close()
            self.SetFileAccept(path)
            # WriteLog('TYPE_FILE','FILE_CREATE_SUCCESS',(path,))
            return returnMsg(True, 'FILE_CREATE_SUCCESS')
        except:
            return returnMsg(False, 'FILE_CREATE_ERR')

    # 创建目录
    def CreateDir(self, get):
        path = bytes.decode(get.get('path').encode('utf-8'))
        while path.startswith('/'):
            path = path[1:]
        path = os.path.join("/", path)
        try:
            if not self.CheckFileName(path): return returnMsg(False, '目录名中不能包含特殊字符!')
            if os.path.exists(path):
                return returnMsg(False, 'DIR_EXISTS')
            os.makedirs(path)
            self.SetFileAccept(path)
            # public.WriteLog('TYPE_FILE','DIR_CREATE_SUCCESS',(get.path,))
            return returnMsg(True, 'DIR_CREATE_SUCCESS')
        except:
            return returnMsg(False, 'DIR_CREATE_ERR')

    # 删除目录
    def DeleteDir(self, get):
        path = bytes.decode(get.get('path').encode('utf-8'))
        while path.startswith('/'):
            path = path[1:]
        path = os.path.join("/", path)
        # if get.path.find('/www/wwwroot') == -1: return public.returnMsg(False,'此为演示服务器,禁止删除此目录!')
        if not os.path.exists(path):
            return returnMsg(False, 'DIR_NOT_EXISTS')

        # 检查是否敏感目录
        if not self.CheckDir(path):
            return returnMsg(False, 'FILE_DANGER')

        try:
            # 检查是否存在.user.ini
            if os.path.exists(os.path.join(path, '.user.ini')):
                os.system("chattr -i '" + os.path.join(path, '.user.ini'))
            if 'empty' in get:
                if not self.delete_empty(path): return returnMsg(False, 'DIR_ERR_NOT_EMPTY')

            if os.path.exists(os.path.join(self.BASE_DIR,'recycle_bin.pl')):
                if self.Mv_Recycle_bin(get): return returnMsg(True, 'DIR_MOVE_RECYCLE_BIN')

            import shutil
            shutil.rmtree(path)
            # public.WriteLog('TYPE_FILE','DIR_DEL_SUCCESS',(get.path,))
            return returnMsg(True, 'DIR_DEL_SUCCESS')
        except:
            return returnMsg(False, 'DIR_DEL_ERR')

    # 删除 空目录
    def delete_empty(self, path):
        for files in os.listdir(path):
            return False
        return True

    # 删除文件
    def DeleteFile(self, get):
        path = bytes.decode(get.get('path').encode('utf-8'))
        while path.startswith('/'):
            path = path[1:]
        path = os.path.join("/", path)
        if not os.path.exists(path):
            return returnMsg(False, 'FILE_NOT_EXISTS')

        # 检查是否为.user.ini
        if path.find('.user.ini'):
            os.system("chattr -i '" + path + "'")
        try:
            if os.path.exists(os.path.join(self.BASE_DIR, 'recycle_bin.pl')):
                if self.Mv_Recycle_bin(get): return returnMsg(True, 'FILE_MOVE_RECYCLE_BIN')
            os.remove(path)
            # public.WriteLog('TYPE_FILE','FILE_DEL_SUCCESS',(get.path,))
            return returnMsg(True, 'FILE_DEL_SUCCESS')
        except:
            return returnMsg(False, 'FILE_DEL_ERR')

    # 移动到回收站
    def Mv_Recycle_bin(self, get,filename=""):
        if filename != "":
            path=filename
        else:
            path = bytes.decode(get.get('path').encode('utf-8'))
        while path.startswith('/'):
            path = path[1:]
        path = os.path.join("/", path)
        # print("Mv_Recycle_bin",path)
        rPath = '/www/Recycle_bin/'
        if not os.path.exists(rPath): os.system('mkdir -p ' + rPath)
        rFile = rPath + path.replace('/', '_bt_') + '_t_' + str(time.time())
        try:
            import shutil
            shutil.move(path, rFile)
            # public.WriteLog('TYPE_FILE','FILE_MOVE_RECYCLE_BIN',(get.path,))
            return True
        except:
            # public.WriteLog('TYPE_FILE','FILE_MOVE_RECYCLE_BIN_ERR',(get.path,))
            return False

    # 从回收站恢复
    def Re_Recycle_bin(self, get):
        path = bytes.decode(get.get('path').encode('utf-8'))
        rPath = '/www/Recycle_bin/'

        dFile = path.replace('_bt_', '/').split('_t_')[0]
        path = os.path.join(rPath, path)
        try:
            import shutil
            shutil.move(path, dFile)
            # public.WriteLog('TYPE_FILE','FILE_RE_RECYCLE_BIN',(dFile,))
            return returnMsg(True, 'FILE_RE_RECYCLE_BIN')
        except:
            # public.WriteLog('TYPE_FILE','FILE_RE_RECYCLE_BIN_ERR',(dFile,))
            return returnMsg(False, 'FILE_RE_RECYCLE_BIN_ERR')

    # 获取回收站信息
    def Get_Recycle_bin(self, get):
        rPath = '/www/Recycle_bin/'
        if not os.path.exists(rPath): os.system('mkdir -p ' + rPath)
        data = {}
        data['dirs'] = []
        data['files'] = []
        data['status'] = os.path.exists(os.path.join(self.BASE_DIR, 'recycle_bin.pl'))
        data['status_db'] = os.path.exists(os.path.join(self.BASE_DIR, 'recycle_bin_db.pl'))
        for file in os.listdir(rPath):
            try:
                tmp = {}
                fname = os.path.join(rPath, file)
                tmp1 = file.split('_bt_')
                tmp2 = tmp1[len(tmp1) - 1].split('_t_')
                tmp['rname'] = file
                tmp['dname'] = file.replace('_bt_', '/').split('_t_')[0]
                tmp['name'] = tmp2[0]
                tmp['time'] = int(float(tmp2[1]))
                if os.path.islink(fname):
                    filePath = os.readlink(fname)
                    link = ' -> ' + filePath
                    if os.path.exists(filePath):
                        tmp['size'] = os.path.getsize(filePath)
                    else:
                        tmp['size'] = 0
                else:
                    tmp['size'] = os.path.getsize(fname)
                if os.path.isdir(fname):
                    data['dirs'].append(tmp)
                else:
                    data['files'].append(tmp)
            except Exception as e:
                # print("获取回收站异常", e)
                continue
        return data

    # 彻底删除
    def Del_Recycle_bin(self, get):
        rPath = '/www/Recycle_bin/'
        path = bytes.decode(get.get('path').encode('utf-8'))
        dFile = path.split('_t_')[0]
        if not self.CheckDir(os.path.join(rPath, path)):
            return returnMsg(False, 'FILE_DANGER')
        os.system('chattr -R -i ' + os.path.join(rPath, path))
        if os.path.isdir(os.path.join(rPath, path)):
            import shutil
            shutil.rmtree(os.path.join(rPath, path))
        else:
            os.remove(os.path.join(rPath, path))

        tfile = path.replace('_bt_', '/').split('_t_')[0]
        # public.WriteLog('TYPE_FILE','FILE_DEL_RECYCLE_BIN',(tfile,))
        return returnMsg(True, 'FILE_DEL_RECYCLE_BIN', (tfile,))

    # 清空回收站
    def Close_Recycle_bin(self, get):
        rPath = '/www/Recycle_bin/'
        os.system('chattr -R -i ' + rPath)
        import shutil
        rlist = os.listdir(rPath)
        i = 0
        l = len(rlist)
        for name in rlist:
            i += 1
            path = rPath + name
            writeSpeed(name, i, l)
            if os.path.isdir(path):
                # os.system('rm -rf ' + path)
                shutil.rmtree(path)
            else:
                # os.system('rm -f ' + path)
                os.remove(path)
        writeSpeed(None, 0, 0)
        # public.WriteLog('TYPE_FILE','FILE_CLOSE_RECYCLE_BIN')
        return returnMsg(True, 'FILE_CLOSE_RECYCLE_BIN')

    # 回收站开关
    def Recycle_bin(self, get):
        c = 'recycle_bin.pl'
        if 'db' in get: c = 'recycle_bin_db.pl'
        cpath = os.path.join(self.BASE_DIR, c)
        if os.path.exists(cpath):
            os.remove(cpath)
            # public.WriteLog('TYPE_FILE','FILE_OFF_RECYCLE_BIN')
            return returnMsg(True, 'FILE_OFF_RECYCLE_BIN')
        else:
            writeFile(cpath, 'True')
            # public.WriteLog('TYPE_FILE','FILE_ON_RECYCLE_BIN')
            return returnMsg(True, 'FILE_ON_RECYCLE_BIN')

    # 复制文件
    def CopyFile(self, get):
        path = bytes.decode(get.get('sfile').encode('utf-8'))
        while path.startswith('/'):
            path = path[1:]
        sfile = os.path.join("/", path)

        path = bytes.decode(get.get('dfile').encode('utf-8'))
        while path.startswith('/'):
            path = path[1:]
        dfile = os.path.join("/", path)

        if not os.path.exists(sfile):
            return returnMsg(False, 'FILE_NOT_EXISTS')

        # if os.path.exists(get.dfile):
        #    return public.returnMsg(False,'FILE_EXISTS')

        if os.path.isdir(sfile):
            return self.CopyDir(get)

        import shutil
        try:
            shutil.copyfile(sfile, dfile)
            # public.WriteLog('TYPE_FILE','FILE_COPY_SUCCESS',(get.sfile,get.dfile))
            stat = os.stat(sfile)
            os.chown(dfile, stat.st_uid, stat.st_gid)
            return returnMsg(True, 'FILE_COPY_SUCCESS')
        except:
            return returnMsg(False, 'FILE_COPY_ERR')

    # 复制文件夹
    def CopyDir(self, get):
        path = bytes.decode(get.get('sfile').encode('utf-8'))
        while path.startswith('/'):
            path = path[1:]
        sfile = os.path.join("/", path)

        path = bytes.decode(get.get('dfile').encode('utf-8'))
        while path.startswith('/'):
            path = path[1:]
        dfile = os.path.join("/", path)
        if not os.path.exists(sfile):
            return returnMsg(False, 'DIR_NOT_EXISTS')

        if os.path.exists(dfile):
            return returnMsg(False, 'DIR_EXISTS')

        # if not self.CheckDir(get.dfile):
        #    return public.returnMsg(False,'FILE_DANGER')

        import shutil
        try:
            shutil.copytree(sfile, dfile)
            stat = os.stat(sfile)
            os.chown(dfile, stat.st_uid, stat.st_gid)
            # public.WriteLog('TYPE_FILE','DIR_COPY_SUCCESS',(get.sfile,get.dfile))
            return returnMsg(True, 'DIR_COPY_SUCCESS')
        except:
            return returnMsg(False, 'DIR_COPY_ERR')

    # 移动文件或目录
    def MvFile(self, get):

        path = bytes.decode(get.get('sfile').encode('utf-8'))
        while path.startswith('/'):
            path = path[1:]
        sfile = os.path.join("/", path)

        path = bytes.decode(get.get('dfile').encode('utf-8'))
        while path.startswith('/'):
            path = path[1:]
        dfile = os.path.join("/", path)

        if not self.CheckFileName(dfile): return returnMsg(False, '文件名中不能包含特殊字符!')
        if not os.path.exists(sfile):
            return returnMsg(False, 'FILE_NOT_EXISTS')

        # if os.path.exists(get.dfile):
        #    return public.returnMsg(False,'FILE_EXISTS')

        if not self.CheckDir(sfile):
            return returnMsg(False, 'FILE_DANGER')

        import shutil
        try:
            shutil.move(sfile, dfile)
            # public.WriteLog('TYPE_FILE','MOVE_SUCCESS',(get.sfile,get.dfile))
            return returnMsg(True, 'MOVE_SUCCESS')
        except:
            return returnMsg(False, 'MOVE_ERR')

    # 检查文件是否存在
    def CheckExistsFiles(self, get):
        path = bytes.decode(get.get('dfile').encode('utf-8'))
        while path.startswith('/'):
            path = path[1:]
        dfile = os.path.join("/", path)

        data = []
        filesx = []
        if 'filename' in get:
            filesx.append(bytes.decode(get.get('filename').encode('utf-8')))
        for fn in filesx:
            filename = os.path.join(dfile, fn)
            if os.path.exists(filename):
                tmp = {}
                stat = os.stat(filename)
                tmp['filename'] = fn
                tmp['size'] = os.path.getsize(filename)
                tmp['mtime'] = str(int(stat.st_mtime))
                data.append(tmp)
        return data

    # 获取文件内容
    def GetFileBody(self, get):
        path = bytes.decode(get.get('path').encode('utf-8'))
        while path.startswith('/'):
            path = path[1:]
        path = os.path.join("/", path)
        if not os.path.exists(path):
            if path.find('rewrite') == -1:
                return returnMsg(False, 'FILE_NOT_EXISTS')
            writeFile(path, '')

        if os.path.getsize(path) > 2097152: return returnMsg(False, '不能在线编辑大于2MB的文件!')
        srcBody = readFile(path)
        data = {}
        # print(type(srcBody))
        data['status'] = True
        try:
            if srcBody:
                try:
                    import chardet
                    char = chardet.detect(srcBody)
                except Exception as ex:
                    return returnMsg(False, str(ex))
                data['encoding'] = char['encoding']
                if char['encoding'] == 'GB2312' or not char['encoding'] or char['encoding'] == 'TIS-620' or char[
                    'encoding'] == 'ISO-8859-9': data['encoding'] = 'GBK'
                if char['encoding'] == 'ascii' or char['encoding'] == 'ISO-8859-1': data['encoding'] = 'utf-8'
                if char['encoding'] == 'Big5': data['encoding'] = 'BIG5'
                if not char['encoding'] in ['GBK', 'utf-8', 'BIG5']: data['encoding'] = 'utf-8'
                try:
                    data['data'] = str(srcBody.decode(data['encoding']).encode('utf-8'), encoding='utf8')
                except:
                    data['encoding'] = char['encoding']
                    data['data'] = str(srcBody.decode(data['encoding']).encode('utf-8'), encoding='utf8')
            else:
                data['data'] = str(srcBody.decode('utf-8').encode('utf-8'), encoding='utf8')
                data['encoding'] = 'utf-8'
            return data
        except Exception as ex:
            return returnMsg(False, '文件编码不被兼容，无法正确读取文件!' + str(ex))

    # 保存文件
    def SaveFileBody(self, get):
        path = bytes.decode(get.get('path').encode('utf-8'))
        while path.startswith('/'):
            path = path[1:]
        path = os.path.join("/", path)
        if not os.path.exists(path):
            if get.path.find('.htaccess') == -1:
                return returnMsg(False, 'FILE_NOT_EXISTS')

        try:
            isConf = -1
            if os.path.exists('/etc/init.d/nginx') or os.path.exists('/etc/init.d/httpd'):
                isConf = path.find('nginx')
                if isConf == -1: isConf = path.find('apache')
                if isConf == -1: isConf = path.find('rewrite')
                if isConf != -1:
                    os.system('\\cp -a ' + path + ' /tmp/backup.conf')

            data = get.get('data')
            userini = False
            if path.find('.user.ini') != -1:
                userini = True
                ExecShell('chattr -i ' + get.path)

            if path.find('/www/server/cron') != -1:
                try:
                    import crontab
                    data = crontab.crontab().CheckScript(data)
                except:
                    pass
            encods = get.get('encoding')
            if encods == 'ascii': encods = 'utf-8'
            writeFile(path, data.encode(encods))
            if isConf != -1:
                isError = checkWebConfig()
                if isError != True:
                    os.system('\\cp -a /tmp/backup.conf ' + path)
                    return returnMsg(False,
                                     'ERROR:<br><font style="color:red">' + isError.replace("\n", '<br>') + '</font>')
                # serviceReload()

            if userini: ExecShell('chattr +i ' + get.path)

            # WriteLog('TYPE_FILE','FILE_SAVE_SUCCESS',(get.path,))
            return returnMsg(True, 'FILE_SAVE_SUCCESS')
        except:
            return returnMsg(False, 'FILE_SAVE_ERR')

    # 文件压缩
    def Zip(self, get):
        import os
        sfile = bytes.decode(get.get('sfile').encode('utf-8'))

        getpath = bytes.decode(get.get('dfile').encode('utf-8'))
        while getpath.startswith('/'):
            getpath = getpath[1:]
        dfile = os.path.join("/", getpath)

        getpath = bytes.decode(get.get('path').encode('utf-8'))
        while getpath.startswith('/'):
            getpath = getpath[1:]
        getpath = os.path.join("/", getpath)

        type = bytes.decode(get.get('type').encode('utf-8'))
        sfilefullpath = getpath
        # print({'sfile': sfile, 'dfile': dfile, 'type': type, 'path': getpath})

        if sfile.find(',') == -1:
            if not os.path.exists(os.path.join(getpath, sfile)): return returnMsg(False, 'FILE_NOT_EXISTS')
        try:
            tmps = '/tmp/panelExec.log'
            if type == 'zip':
                os.system("cd '" + getpath + "' && zip '" + dfile + "' -r '" + sfile + "' > " + tmps + " 2>&1")
            else:
                sfiles = ''
                for sfile in sfile.split(','):
                    if not sfile: continue
                    sfiles += " '" + sfile + "'"
                os.system("cd '" + getpath + "' && tar -zcvf '" + dfile + "' " + sfiles + " > " + tmps + " 2>&1")
            self.SetFileAccept(dfile)
            # public.WriteLog("TYPE_FILE", 'ZIP_SUCCESS',(get.sfile,get.dfile))
            return returnMsg(True, 'ZIP_SUCCESS')
        except:
            return returnMsg(False, 'ZIP_ERR')

    # 文件解压
    def UnZip(self, get):
        getpath = bytes.decode(get.get('dfile').encode('utf-8'))
        while getpath.startswith('/'):
            getpath = getpath[1:]
        dfile = os.path.join("/", getpath)

        getpath = bytes.decode(get.get('sfile').encode('utf-8'))
        while getpath.startswith('/'):
            getpath = getpath[1:]
        sfile = os.path.join("/", getpath)

        if not os.path.exists(sfile):
            return returnMsg(False, 'FILE_NOT_EXISTS')
        if 'password' in get: password = ''

        # try:
        coding = bytes.decode(get.get('coding').encode('utf-8'))
        if 'coding' in get: coding = 'UTF-8'
        tmps = '/tmp/panelExec.log'
        if sfile[-4:] == '.zip':
            os.system(
                "export LANG=\"zh_CN." + coding + "\" && unzip -P '" + password + "' -o '" + sfile + "' -d '" + dfile + "' > " + tmps + " 2>&1")
        elif sfile[-7:] == '.tar.gz' or sfile[-4:] == '.tgz':
            os.system("tar zxf '" + sfile + "' -C '" + dfile + "' > " + tmps + " 2>&1")
        else:
            os.system("gunzip -c " + sfile + " > " + sfile[:-3])
        # if self.CheckDir(dfile):
        # sites_path = public.M('config').where('id=?',(1)).getField('sites_path')
        # if get.dfile.find('/www/wwwroot') != -1 or get.dfile.find(sites_path) != -1: self.SetFileAccept(get.dfile)
        # public.WriteLog("TYPE_FILE", 'UNZIP_SUCCESS',(get.sfile,get.dfile))
        return returnMsg(True, 'UNZIP_SUCCESS')
        # except:
        #    return public.returnMsg(False,'文件解压失败!')

    # 获取文件/目录 权限信息
    def GetFileAccess(self, get):
        getpath = bytes.decode(get.get('filename').encode('utf-8'))
        while getpath.startswith('/'):
            getpath = getpath[1:]
        filename = os.path.join("/", getpath)
        data = {}
        try:
            import pwd
            stat = os.stat(filename)
            data['chmod'] = str(oct(stat.st_mode)[-3:])
            data['chown'] = pwd.getpwuid(stat.st_uid).pw_name
        except:
            data['chmod'] = 755
            data['chown'] = 'www'
        return data

    # 设置文件权限和所有者
    def SetFileAccess(self, get, all='-R'):
        getpath = bytes.decode(get.get('filename').encode('utf-8'))
        while getpath.startswith('/'):
            getpath = getpath[1:]
        filename = os.path.join("/", getpath)
        access = bytes.decode(get.get('access').encode('utf-8'))
        user = bytes.decode(get.get('user').encode('utf-8'))
        try:
            if not self.CheckDir(filename): return returnMsg(False, 'FILE_DANGER')
            if not os.path.exists(filename):
                return returnMsg(False, 'FILE_NOT_EXISTS')
            os.system('chmod ' + all + ' ' + access + " '" + filename + "'")
            os.system('chown ' + all + ' ' + user + ':' + user + " '" + filename + "'")
            # public.WriteLog('TYPE_FILE','FILE_ACCESS_SUCCESS',(filename,access,user))
            return returnMsg(True, 'SET_SUCCESS')
        except:
            return returnMsg(False, 'SET_ERROR')

    def SetFileAccept(self, filename):
        os.system('chown -R www:www ' + filename)
        os.system('chmod -R 755 ' + filename)

    # 取目录大小
    def GetDirSize(self, get):
        path = bytes.decode(get.get('path').encode('utf-8'))
        while path.startswith('/'):
            path = path[1:]
        path = os.path.join("/", path)
        tmp = ExecShell('du -sbh ' + path)
        return bytes.decode(tmp[0]).split()[0]

    # def CloseLogs(self,get):
    #     import web
    #     get.path = web.ctx.session.rootPath
    #     os.system('rm -f '+web.ctx.session.logsPath+'/*')
    #     if public.get_webserver() == 'nginx':
    #         os.system('kill -USR1 `cat '+web.ctx.session.setupPath+'/nginx/logs/nginx.pid`')
    #     else:
    #         os.system('/etc/init.d/httpd reload')
    #
    #     public.WriteLog('TYPE_FILE','SITE_LOG_CLOSE')
    #     get.path = web.ctx.session.logsPath
    #     return self.GetDirSize(get)

    # 批量操作
    def SetBatchData(self, get, request):
        path = bytes.decode(get.get('path').encode('utf-8'))
        data = get.getlist('data')
        while path.startswith('/'):
            path = path[1:]
        path = os.path.join("/", path)
        type = bytes.decode(get.get('type').encode('utf-8'))
        if type == '1' or type == '2':
            request.session['data'] = json.dumps(data)
            request.session['path'] = path
            return returnMsg(True, 'FILE_ALL_TIPS')
        elif type == '3':
            for key in data:
                try:
                    access = bytes.decode(get.get('access').encode('utf-8'))
                    user = bytes.decode(get.get('user').encode('utf-8'))
                    filename = os.path.join(path ,key)
                    if not self.CheckDir(filename): return returnMsg(False, 'FILE_DANGER')
                    os.system('chmod -R ' + access + " '" + filename + "'")
                    os.system('chown -R ' + user + ':' + user + " '" + filename + "'")
                except:
                    continue
            # public.WriteLog('TYPE_FILE','FILE_ALL_ACCESS')
            return returnMsg(True, 'FILE_ALL_ACCESS')
        else:
            import shutil
            isRecyle = os.path.exists(os.path.join(self.BASE_DIR, 'recycle_bin.pl'))
            l = len(data)
            i = 0
            for key in data:
                try:
                    filename = os.path.join(path, key)
                    # path = filename
                    if not os.path.exists(filename): continue
                    i += 1
                    writeSpeed(key, i, l)
                    if os.path.isdir(filename):
                        if not self.CheckDir(filename): return returnMsg(False, 'FILE_DANGER')
                        if isRecyle:
                            self.Mv_Recycle_bin(get,filename)
                        else:
                            shutil.rmtree(filename)
                    else:
                        if key == '.user.ini': os.system('chattr -i ' + filename)
                        if isRecyle:
                            self.Mv_Recycle_bin(get,filename)
                        else:
                            os.remove(filename)
                except:
                    continue
                writeSpeed(None, 0, 0)
            # public.WriteLog('TYPE_FILE','FILE_ALL_DEL')
            return returnMsg(True, 'FILE_ALL_DEL')

    # 批量粘贴
    def BatchPaste(self, get, request):
        import shutil
        path = bytes.decode(get.get('path').encode('utf-8'))
        while path.startswith('/'):
            path = path[1:]
        path = os.path.join("/", path)
        if not os.path.exists(path): path = '/'
        # if not self.CheckDir(path): return returnMsg(False,'FILE_DANGER')
        i = 0
        data = json.loads(request.session.get("data"))
        sesspath = request.session.get("path")
        l = len(data)
        type = bytes.decode(get.get('type').encode('utf-8'))
        if type == '1':
            for key in data:
                i += 1
                writeSpeed(key, i, l)
                try:
                    sfile = os.path.join(sesspath, key)
                    dfile = os.path.join(path, key)
                    if os.path.isdir(sfile):
                        shutil.copytree(sfile, dfile)
                    else:
                        shutil.copyfile(sfile, dfile)
                    stat = os.stat(sfile)
                    os.chown(dfile, stat.st_uid, stat.st_gid)
                except:
                    continue
            # public.WriteLog('TYPE_FILE','FILE_ALL_COPY',(web.ctx.session.selected.path,get.path))
        else:
            for key in data:
                try:
                    i += 1
                    writeSpeed(key, i, l)
                    sfile = os.path.join(sesspath, key)
                    dfile = os.path.join(path, key)
                    shutil.move(sfile, dfile)
                except:
                    continue
            # public.WriteLog('TYPE_FILE','FILE_ALL_MOTE',(web.ctx.session.selected.path,get.path))
        writeSpeed(None, 0, 0)
        errorCount = len(data) - i
        del (request.session['data'])
        del (request.session['path'])
        return returnMsg(True, 'FILE_ALL', (str(i), str(errorCount)))

    # 下载文件
    # def DownloadFile(self,get):
    #     get.path = get.path.encode('utf-8')
    #     import db,time
    #     isTask = '/tmp/panelTask.pl'
    #     execstr = get.url +'|bt|'+get.path+'/'+get.filename
    #     sql = db.Sql()
    #     sql.table('tasks').add('name,type,status,addtime,execstr',('下载文件['+get.filename+']','download','0',time.strftime('%Y-%m-%d %H:%M:%S'),execstr))
    #     public.writeFile(isTask,'True')
    #     self.SetFileAccept(get.path+'/'+get.filename)
    #     public.WriteLog('TYPE_FILE','FILE_DOWNLOAD',(get.url , get.path))
    #     return public.returnMsg(True,'FILE_DOANLOAD')

    # 取执行日志
    # def GetExecLog(self,get):
    #     return self.GetLastLine('/tmp/panelExec.log',100)

    # 读文件指定倒数行数
    # def GetLastLine(self,inputfile,lineNum):
    #     try:
    #         fp = open(inputfile, 'r')
    #         lastLine = ""
    #
    #         lines =  fp.readlines()
    #         count = len(lines)
    #         if count>lineNum:
    #             num=lineNum
    #         else:
    #             num=count
    #         i=1
    #         lastre = []
    #         for i in range(1,(num+1)):
    #             if lines :
    #                 n = -i
    #                 lastLine = lines[n].strip()
    #                 fp.close()
    #                 lastre.append(lastLine)
    #
    #         result = ''
    #         lineNum -= 1
    #         while lineNum > 0:
    #             result += lastre[lineNum]+"\n"
    #             lineNum -= 1
    #
    #         return result
    #     except:
    #         return public.getMsg('TASK_SLEEP')

#     #执行SHELL命令
#     def ExecShell(self,get):
#         disabled = ['vi','vim','top','passwd','su']
#         get.shell = get.shell.strip()
#         tmp = get.shell.split(' ')
#         if tmp[0] in disabled: return returnMsg(False,'FILE_SHELL_ERR',(tmp[0],))
#         shellStr = '''#!/bin/bash
# PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
# export PATH
# cd %s
# %s
# ''' % (get.path,get.shell)
#         public.writeFile('/tmp/panelShell.sh',shellStr)
#         os.system('nohup bash /tmp/panelShell.sh > /tmp/panelShell.pl 2>&1 &')
#         return public.returnMsg(True,'FILE_SHELL_EXEC')
#
#     #取SHELL执行结果
#     def GetExecShellMsg(self,get):
#         fileName = '/tmp/panelShell.pl'
#         if not os.path.exists(fileName): return 'FILE_SHELL_EMPTY'
#         return public.readFile('/tmp/panelShell.pl')

# 文件搜索
# def GetSearch(self,get):
#     if not os.path.exists(get.path): return returnMsg(False,'DIR_NOT_EXISTS')
#     return ExecShell("find "+get.path+" -name '*"+get.search+"*'")

def encodes(info):
    import base64
    infostr = json.dumps(info)
    jiamistr = base64.urlsafe_b64encode(str.encode(infostr, encoding='utf8'))
    return jiamistr


def execposts(request):
    postdata = request.POST
    getdata = request.GET.dict()
    # print(request.__dict__)
    fileobj = files()
    dirlist = []
    actions = getdata.get('action')
    if actions == "GetDir":
        dirlist = fileobj.GetDir(getdata, postdata)
    elif actions == "GetFileBody":
        dirlist = fileobj.GetFileBody(postdata)
    elif actions == "SaveFileBody":
        dirlist = fileobj.SaveFileBody(postdata)
    elif actions == "CreateFile":
        dirlist = fileobj.CreateFile(postdata)
    elif actions == "MvFile":
        dirlist = fileobj.MvFile(postdata)
    elif actions == "DeleteFile":
        dirlist = fileobj.DeleteFile(postdata)
    elif actions == "Recycle_bin":
        dirlist = fileobj.Recycle_bin(postdata)
    elif actions == "Zip":
        dirlist = fileobj.Zip(postdata)
    elif actions == "UnZip":
        dirlist = fileobj.UnZip(postdata)
    elif actions == "GetDirSize":
        dirlist = fileobj.GetDirSize(postdata)
    elif actions == "GetFileAccess":
        dirlist = fileobj.GetFileAccess(postdata)
    elif actions == "SetFileAccess":
        dirlist = fileobj.SetFileAccess(postdata)
    elif actions == "CheckExistsFiles":
        dirlist = fileobj.CheckExistsFiles(postdata)
    elif actions == "CopyFile":
        dirlist = fileobj.CopyFile(postdata)
    elif actions == "SetBatchData":
        dirlist = fileobj.SetBatchData(postdata, request)
    elif actions == "BatchPaste":
        dirlist = fileobj.BatchPaste(postdata, request)
    elif actions == "GetSpeed":
        dirlist = fileobj.getSpeed()
    elif actions == "Get_Recycle_bin":
        dirlist = fileobj.Get_Recycle_bin(postdata)
    elif actions == "Re_Recycle_bin":
        dirlist = fileobj.Re_Recycle_bin(postdata)
    elif actions == "Close_Recycle_bin":
        dirlist = fileobj.Close_Recycle_bin(postdata)
    elif actions == "Del_Recycle_bin":
        dirlist = fileobj.Del_Recycle_bin(postdata)
    elif actions == "DeleteDir":
        dirlist = fileobj.DeleteDir(postdata)
    elif actions == "CreateDir":
        dirlist = fileobj.CreateDir(postdata)
    return dirlist